#!/usr/bin/python
# -*- coding: utf-8 -*-
# @version        : 1.0
# @Create Time    : 2024/9/6 11:11
# @File           : __init__
# @IDE            : PyCharm
# @desc           : 描述

from datetime import datetime
from core.crud import DalBase
from sqlalchemy.ext.asyncio import AsyncSession
from . import models, schemas
from core.exception import CustomException
from apps.check.param.crud import ParamDal
from apps.check.female.crud import QARFemaleDal
from apps.check.female.schemas import QARContentTypeEnum
from apps.check.plan.crud import PlanDal
from apps.check.plan.schemas import PlanFemaleMissingIn
from apps.check.asr.crud import ASRDal
from apps.check.asr.schemas import ASRIn
from apps.check.order.crud import OrderDal
from apps.check.order.schemas import Order
from apps.check.sample.crud import SampleGroupDal, SampleStandardDal


class QARDal(DalBase):

    def __init__(self, db: AsyncSession):
        super(QARDal, self).__init__()
        self.db = db
        self.model = models.DCQAR
        self.schema = schemas.QARSimpleOut

    @staticmethod
    def _generate_serial_no(value):
        if not value:
            return '0001'
        value = str(int(value) + 1)
        return '0' * (4 - len(value)) + value
    
    async def generate_qar_no(self, data: schemas.QARIn):
        qar_no = "QAR-{product_type}{part_type}{short_year}-"
        values = {
            'short_year': datetime.now().strftime('%Y')[-2:],
            'product_type': '',
            'part_type': '',
        }
        params = await ParamDal(self.db).get_datas(param_type=("in", ['型号', '材料']), v_return_objs=True)

        for param in params:
            if param.param_type == '型号' and param.param_name == data.product_type:
                values['product_type'] = param.param_value
            elif param.param_type == '材料' and param.param_name == data.part_type:
                values['part_type'] = param.param_value
                data.form_type = param.param_detail
        
        if not values['product_type'] or not values['part_type']:
            raise CustomException("请先在参数管理中，定义'型号'和'材料'类型参数，用于生成QAR编号")
        
        qar_no = qar_no.format(**values)
        datas = await self.get_datas(limit=1, v_order='desc', qar_no=("like", qar_no), v_return_objs=True)
        data.qar_no = qar_no + self._generate_serial_no(datas[0].qar_no[-4:] if datas else None)

    async def match_qar_female(self, data: schemas.QARIn):
        female = await QARFemaleDal(self.db).get_data(part_no=data.part_no, status="启用", v_return_none=True)
        if not female:
            await PlanDal(self.db).create_data(
                PlanFemaleMissingIn(
                    part_no=data.part_no,
                    part_name=data.part_name,
                    form_no=data.purchase_order,
                    create_user=data.create_user
                )
            )
            await self.db.commit()
            raise CustomException("未创建对应零件母本，已加入计划待办")
        else:
            data.update(female)

    async def generate_other_form(self, data: schemas.QARIn):
        if data.is_test:
            is_ndt, is_pclr, pclr_mat = False, False, None
            description_map = {
                "part_name": "零件名称",
                "part_no": "零件号",
                "rev_letter": "更改字母",
                "spec_stan": "规范/标准",
                "spec_stan_rev": "规范/标准版次",
                "zpm_cpm": "工艺材料编号",
                "typing": "型别",
                "classing": "类别/组合物别",
                "grade": "级别",
                "form": "形态/形式",
                "size": "规格",
                "color": "色号",
                "special_property": "性能要求"
            }
            description = [v + ":" + getattr(data, k) for k, v in description_map.items() if hasattr(data, k) and getattr(data, k)]
            description = "; ".join(description)

            for item in data.contents:
                if item.content_type != QARContentTypeEnum.test.value:
                    continue
                if item.project == "无损检测 NDT":
                    is_ndt = True
                elif "MAT" in item.project:
                    is_pclr = True
                    pclr_mat = 'MAT NO. ' + item.detail_value[0]
            
            if is_pclr:
                schema = Order(
                    order_type="PCLR",
                    order_no=data.qar_no + "-PCLR",
                    qar_no=data.qar_no,
                    product_type=data.product_type,
                    part_type=data.part_type,
                    form_type=data.form_type,
                    material_description=description,
                    vendor=data.vendor,
                    po=data.purchase_order,
                    test_document=pclr_mat,
                    lot_size=data.quantity_weight,
                    status="计划中",
                    create_user=data.create_user
                )
                form = await OrderDal(self.db).create_data(data=schema, v_return_obj=True)
                data.pclr_no = form.order_no

            if is_ndt:
                schema = Order(
                    order_type="NDT",
                    order_no=data.qar_no + "-NDT",
                    qar_no=data.qar_no,
                    product_type=data.product_type,
                    part_type=data.part_type,
                    form_type=data.form_type,
                    material_description=description,
                    vendor=data.vendor,
                    po=data.purchase_order,
                    status="计划中",
                    create_user=data.create_user
                )
                form = await OrderDal(self.db).create_data(data=schema, v_return_obj=True)
                data.ndt_no = form.order_no

        if data.is_sampling and data.asr_features:
            schema = ASRIn(
                asr_no=data.qar_no + "-ASR",
                part_no=data.part_no,
                qar_no=data.qar_no,
                product_type=data.product_type,
                part_type=data.part_type,
                form_type=data.form_type,
                po_fo_no=data.purchase_order,
                mfg_shop_no=data.vendor,
                plan_remark=data.plan_remark,
                insp_remark=data.insp_remark,
                features=data.asr_features,
                quantity=data.quantity_weight, # 来料数
                lot_batch_no=data.lot_batch_no, # 炉批号
                status="计划中",
                create_user=data.create_user
            )
            form = await ASRDal(self.db).create_data(data=schema, v_return_obj=True)
            data.asr_no = form.asr_no


    async def create_data(self, data: schemas.QARIn):
        await self.match_qar_female(data=data)

        if not data.product_type:
            raise CustomException("未指定产品型号，无法生成编号")
        if not data.part_type and not data.material_type:
            raise CustomException("未指定材料/零件类型，无法生成编号")
        elif not data.part_type:
            data.part_type = data.material_type
        
        await self.generate_qar_no(data=data)
        await self.generate_other_form(data=data)

        # 根据 标准/规范 计算试验样本数量
        if data.quantity_weight and data.quantity_weight.isdigit():
            standard = await SampleStandardDal(self.db).get_data(standard=data.spec_stan, is_active=True, v_return_none=True)
            if standard:
                group = await SampleGroupDal(self.db).get_group(group_name=standard.group_name, quantity=int(data.quantity_weight))
                if group: data.pclr_quantity = group.value

            qar = await self.get_data(qar_no=data.qar_no, v_return_none=True)
            if qar:
                return await self.put_data(data_id=qar.id, data=data)
        
        return await super().create_data(data)
    

    async def get_data_detail(self, data_id):
        data = await self.get_data(data_id=data_id)

        data.asr_forms = await ASRDal(self.db).get_datas(qar_no=data.qar_no, limit=0)
        data.order_forms = await OrderDal(self.db).get_datas(qar_no=data.qar_no, limit=0)

        return await self.out_dict(data, v_schema=schemas.QAROut)
    
    async def check_previous(self, qar_no: str):
        order = await OrderDal(self.db).get_data(qar_no=qar_no, v_return_none=True)
        if order and order.status not in ["归档"]:
            raise CustomException("请先完成委托检验")
        asr = await ASRDal(self.db).get_data(qar_no=qar_no, v_return_none=True)
        if asr and asr.status not in ["归档"]:
            raise CustomException("请先完成ASR检验")
